/*******************************************************************************
 * Copyright (c) 2014 Francesco Gabbrielli
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Francesco Gabbrielli - initial API and implementation
 ******************************************************************************/
package it.francescogabbrielli.android.solidalapp;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.services.json.AbstractGoogleJsonClient;
import com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;

public class EndpointsProvider extends ContentProvider {
	
    private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
	private static final String AUTH = EndpointsProvider.class.getPackage().getName()+".endpoints";

    {
	    URI_MATCHER.addURI(AUTH, "Request", 1);
	    URI_MATCHER.addURI(AUTH, "Request/#", 2);
    }

    private Map<String, AbstractGoogleJsonClient> endpoints;

	@Override
	public boolean onCreate() {
		
		endpoints = new LinkedHashMap<String, AbstractGoogleJsonClient>();
		
		return true;
	}
	
	/**
	 * Build the endpoint if needed
	 * 
	 * @param endpoint the name of the endpoint, as returned by uri
	 * 
	 * @return
	 */
	private AbstractGoogleJsonClient getEndpoint(String endpoint) throws Exception {
		
		AbstractGoogleJsonClient ret = endpoints.get(endpoint);
		
		if(ret==null) {
			String name = endpoint + "endpoint";
			Class<?> c = Class.forName(getClass().getPackage().getName()+"."+name.toLowerCase()+"."+name);
			Class<?>[] inner = c.getClasses();
			for(Class<?> bc : inner) {
				if("Builder".equals(bc.getSimpleName())) {
					c = bc;
					break;
				}
			}
			AbstractGoogleJsonClient.Builder builder = (AbstractGoogleJsonClient.Builder) 
					c.getConstructor(
							new Class[] {
									HttpTransport.class,
									JsonFactory.class,
									HttpRequestInitializer.class
							}
					).newInstance(
							new Object[] {
								AndroidHttp.newCompatibleTransport(), 
								new JacksonFactory(),
								new HttpRequestInitializer() {
									@Override
									public void initialize(HttpRequest httpRequest) {
									}
								}
							}
					);
			ret = builder.build();
		}
		
		return ret;
		
	}
	
	@Override
	public String getType(Uri uri) {
		
		String name = uri.getPathSegments().get(0);
		
		switch (URI_MATCHER.match(uri)) {
		
		case 1:
			return "vnd.android.cursor.dir/vnd." + AUTH + "." + name;
			
		case 2:
			return "vnd.android.cursor.item/vnd." + AUTH + "." + name;
			
		default:
			break;
		}
		
		return null;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		
		MatrixCursor cursor = null;
		
		try {
		
			String name = uri.getPathSegments().get(0);
			AbstractGoogleJsonClient endpoint = getEndpoint(name);
						
//			Class<?> c = Class.forName(getClass().getPackage().getName()+"."+name.toLowerCase()+"endpoint.model."+name);
//			List<String> columns = new LinkedList<String>();
//			for(Field f : c.getDeclaredFields())
//				if(f.getModifiers()==Modifier.PRIVATE)
//					columns.add(f.getName());
			cursor = new MatrixCursor(projection);
			
			switch (URI_MATCHER.match(uri)) {
			
			case 1:
				AbstractGoogleJsonClientRequest<?> req = (AbstractGoogleJsonClientRequest<?>)
						endpoint.getClass()
							.getMethod("list"+ name, new Class[] {})
							.invoke(endpoint, new Object[]{});
				Object list = req.execute();
				List<?> items = (List<?>) list.getClass()
							.getMethod("getItems", new Class[]{})
							.invoke(list, new Object[]{});
				
				for(Object item : items) {
					int i=0;
					Object[] values = new Object[projection.length];
					for(String col : projection)
						values[i++] = "_id".equals(col) ? i : item.getClass()
								.getMethod("get"+col.substring(0,1).toUpperCase()+col.substring(1))
								.invoke(item, new Object[] {});
					cursor.addRow(values);
				}
				break;
				
			case 2:
				break;
				
			default:
				break;
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
			
		return cursor;
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		// TODO Auto-generated method stub
		return null;
	}
	

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		// TODO Auto-generated method stub
		return 0;
	}	


}
